#include "PCmodel_ByBlockQueue.hxx"
#include "thread.hpp"
#include <unistd.h>

template <class T>
struct threadData{
    threadData(BLockQueue<T>* data,const string &name)
    :_bq(data)
    ,_ThreadName(name)
    {

    }
    threadData(BLockQueue<T>* data,string &&name)
    :_bq(data)
    ,_ThreadName(name)
    {

    }
    BLockQueue<T> *_bq;
    string _ThreadName;
};

void *comsumer(void *args)
{
    BLockQueue<string> *l_bq = static_cast<threadData<string>*>(args) ->_bq;
    for (int i = 0; i < 100;i++)
    {
        usleep(1000);
        string  a;
        l_bq->C_Pop(&a);
        cout <<static_cast<threadData<string>*>(args)->_ThreadName <<" get::" << a<<"\n";
    }
    return nullptr;
} 

void* producer(void* args)
{
    BLockQueue<string> *l_bq = static_cast<threadData<string>*>(args) ->_bq;
    for (int z = 0; z < 10;z++)
    {
        sleep(1);
        for (int j = 0; j < 2;j++)
            l_bq->P_Push(static_cast<threadData<string>*>(args)->_ThreadName + " >>"+ to_string(z));
        cout << static_cast<threadData<string>*>(args)->_ThreadName<<"Add::" << z<<"\n";
    }
    return nullptr;
}

int main()
{
    BLockQueue<string> *bq = new BLockQueue<string>();
    
    vector<fuh::thread<void *>> thread_array;
    for (int i = 0; i < 3;i++)
    {
        threadData<string>* tdata = new threadData<string>(bq, "");
        tdata->_ThreadName = "Producer-" + to_string(i);
        thread_array.push_back(fuh::thread<void *>(producer, tdata));
    }
    for (int i = 0; i < 2;i++)
    {
        threadData<string>* tdata = new threadData<string>(bq, "");
        tdata->_ThreadName = "Consumer-" + to_string(i);
        thread_array.push_back(fuh::thread<void *>(comsumer, tdata));
    }

    for (int i = 0; i < thread_array.size();i++)
    {
        thread_array[i].Start();
    }
    for(auto &td:thread_array)
    {
        td.join();
    }
    return 0;
}